// 导入Swing库和AWT库，用来做图形用户界面（GUI）的组件和布局管理。
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;

// 定义 GameGUI 类，继承自 JFrame，表示这是一个窗口（窗体）类，用来展示游戏界面。
public class GameGUI extends JFrame {
    // 声明一个 3x3 的按钮数组，用来表示井字棋的每个格子上的按钮。
    private JButton[][] buttons = new JButton[3][3];

    // board 管理棋盘状态（用 Board 类）
    private Board board;
    private HumanPlayer humanPlayer;
    private AIPlayer aiPlayer;

    private GameMode mode;
    private AIPlayer ai1, ai2;
    private HumanPlayer player1, player2;
    private int moveCount = 0;

    private static List<String> gameHistory = new ArrayList<>(); // 存储对局历史

    // 标记游戏是否结束，控制是否还能继续下棋
    private boolean gameOver = false;

    // 构造函数初始化对象
    public GameGUI(GameMode mode) {
        this.mode = mode;
        // 新建棋盘
        this.board = new Board();

        if (mode == GameMode.HUMAN_VS_AI) {
            humanPlayer = new HumanPlayer('X');
            aiPlayer = new AIPlayer('O');
        } else if (mode == GameMode.HUMAN_VS_HUMAN) {
            player1 = new HumanPlayer('X');
            player2 = new HumanPlayer('O');
        } else if (mode == GameMode.AI_VS_AI) {
            ai1 = new AIPlayer('X');
            ai2 = new AIPlayer('O');
        }

        // 设置窗口标题、窗口位置、窗口大小
        setTitle("井字棋 - " + mode);
        //setTitle("井字棋 - " + (mode == GameMode.HUMAN_VS_AI ? "人机对战" : "双人对战"));
        System.out.println("当前模式: " + mode); 
        setSize(400, 450);
        setLocation(600, 300);
        // 关闭窗口时结束程序
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        // 创建一个面板 gridPanel，用3行3列的网格布局管理按钮，确保按钮均匀排列
        JPanel gridPanel = new JPanel(new GridLayout(3, 3));
        // 设置字体，字体为'Arial'，粗体，大小为60，字体对象为 font
        Font font = new Font("Arial", Font.BOLD, 60);

        // 双层循环遍历九个格子
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {

                // 创建一个空文本按钮并设置字体
                // 把循环变量设置给局部变量(当前行 row，当前列col)
                JButton btn = new JButton("");
                btn.setFont(font);
                int row = i, col = j;

                // 给按钮添加点击事件监听器，当按钮被点击时执行下面代码
                btn.addActionListener(e -> {
                    // 只有当游戏未结束且该按钮文本为空（即格子没被占）时才允许被点击(下棋)
                    if (!gameOver && btn.getText().equals("")) {
                        if (mode == GameMode.HUMAN_VS_AI) {
                            // 按钮文本设为人类玩家的符号（X），在界面显示
                            btn.setText(String.valueOf(humanPlayer.getSymbol()));
                            // 调用 Board 的 makeMove 方法，在棋盘数据结构中记录这一步
                            board.makeMove(new Move(row, col), humanPlayer.getSymbol());
                            // 检查游戏状态（是否赢或平局）
                            checkGameStatus(humanPlayer.getSymbol());
                            // 如果游戏没有结束，让ai进行下一步（调用makeaimove)
                            if (!gameOver) makeAIMove();
                        } else if(mode == GameMode.HUMAN_VS_HUMAN) {
                            char currentSymbol = moveCount % 2 == 0 ? 'X' : 'O';
                            btn.setText(String.valueOf(currentSymbol));
                            board.makeMove(new Move(row, col), currentSymbol);
                            checkGameStatus(currentSymbol);
                            moveCount++;
                        } 
                    }
                });

                // 把按钮保存到 buttons 数组，并添加到面板
                buttons[i][j] = btn;
                gridPanel.add(btn);
            }
        }

        // // 创建一个按钮，文本为“重新开始”，绑定点击事件，点击后调用 resetGame() 方法重置游戏
        // JButton resetBtn = new JButton("重新开始");
        // resetBtn.addActionListener(e -> resetGame());

        // 把棋盘按钮面板放在窗口中央
        add(gridPanel, BorderLayout.CENTER);
        // add(resetBtn, BorderLayout.SOUTH);

        // 菜单栏
        JMenuBar menuBar = new JMenuBar();

        JMenu gameMenu = new JMenu("菜单");

        JMenuItem restartItem = new JMenuItem("重新开始");
        restartItem.addActionListener(e -> resetGame());

        JMenuItem historyItem = new JMenuItem("查看对局记录");
        historyItem.addActionListener(e -> showGameHistory());

        gameMenu.add(restartItem);
        gameMenu.add(historyItem);

        menuBar.add(gameMenu);
        setJMenuBar(menuBar);

        setVisible(true);

        if (mode == GameMode.AI_VS_AI) {
            new Thread(this::runAIVsAI).start();
        }
    }// 构造函数调用结束

    // ai走棋方法
    private void makeAIMove() {
        Move move = aiPlayer.makeMove(board.getBoard());
        if (move != null) {
            board.makeMove(move, aiPlayer.getSymbol());
            buttons[move.row][move.col].setText(String.valueOf(aiPlayer.getSymbol()));
            checkGameStatus(aiPlayer.getSymbol());
        }
    }

    private void runAIVsAI() {
        Player current = ai1;
        while (!gameOver) {
            try { Thread.sleep(500); } catch (InterruptedException e) {}
            Move move = current.makeMove(board.getBoard());
            if (move == null) break;
            board.makeMove(move, current.getSymbol());
            buttons[move.row][move.col].setText(String.valueOf(current.getSymbol()));
            checkGameStatus(current.getSymbol());
            current = (current == ai1) ? ai2 : ai1;
        }
    }

    // 查看当前游戏状态
    private void checkGameStatus(char symbol) {
    if (board.checkWin(symbol)) {
        gameOver = true;
        gameHistory.add("玩家 " + symbol + " 获胜");
        JOptionPane.showMessageDialog(this, "玩家 " + symbol + " 获胜！");
    } else if (board.isFull()) {
        gameOver = true;
        gameHistory.add("平局");
        JOptionPane.showMessageDialog(this, "平局！");
        }
    }

    // 对局记录模块
    private void showGameHistory() {
        if (gameHistory.isEmpty()) {
            JOptionPane.showMessageDialog(this, "当前没有对局记录。");
        } else {
            StringBuilder sb = new StringBuilder("对局记录：\n");
            for (int i = 0; i < gameHistory.size(); i++) {
                sb.append("第 ").append(i + 1).append(" 局: ").append(gameHistory.get(i)).append("\n");
            }
            JOptionPane.showMessageDialog(this, sb.toString());
        }
    }

    // 重新开始游戏
    private void resetGame() {
    dispose(); // 关闭当前窗口
    new StartMenu(); // 重新打开开始菜单
    }

}